<template>
  <div class="app-container">
    <div class="top" style="margin-top: 28px;">
      <el-input
        v-model="kwInput"
        placeholder="输入 网站编码 或 域名 进行筛选"
        class="input-with-select"
        clearable
        @keyup.native.enter="handleSearch"
      >
        <el-button slot="append" icon="el-icon-search" :disabled="listLoading" @click="handleSearch">搜索</el-button>
      </el-input>

      <el-button type="primary" class="el-icon-plus add-btn" @click="handleAction('create', '添加配置')">添加配置
      </el-button>

    </div>
    <el-table v-loading.body="listLoading" :data="data" border fit highlight-current-row style="width: 100%">
      <el-table-column align="center" label="网站列表" prop="websites" sortable="custom" width="300">
        <template slot-scope="scope">
          <el-badge :value="scope.row.websites.length" class="item">
            <el-dropdown v-if="scope.row.websites.length" trigger="click">
              <span class="el-dropdown-link">
                {{ scope.row.websites[0].domain }}<i class="el-icon-caret-bottom el-icon--right" />
              </span>
              <el-dropdown-menu slot="dropdown">
                <el-dropdown-item v-for="(item,index) in scope.row.websites" :key="index" class="clearfix">
                  <a @click="handleViewBackups(scope.row,item.id,item.domain)">{{ item.domain }}</a>
                </el-dropdown-item>
              </el-dropdown-menu>
            </el-dropdown>
          </el-badge>
        </template>
      </el-table-column>
      <el-table-column align="center" label="GSAPI" width="260">
        <template slot-scope="scope">
          <span>{{ 'http://' + scope.row.gsapi_ip + ':' + scope.row.gsapi_port }}</span>
        </template>
      </el-table-column>
      <el-table-column align="center" label="isp" prop="isp" width="200">
        <template slot-scope="scope">
          <el-popover
            placement="top-start"
            title="详情"
            width="600"
            trigger="hover"
          >
            <div>
              <el-row>
                <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
                  <p>内存:{{ scope.row.memory_used }}/{{ scope.row.memory_total }}</p>
                  <p>交换分区:{{ scope.row.swap_used }}/{{ scope.row.swap_total }}</p>
                  <p>硬盘:{{ scope.row.hdd_used }}/{{ scope.row.hdd_total }}</p>
                  <p>负载:{{ scope.row.load_1 }}, CPU:{{ scope.row.cpu }}</p>
                  <p>
                    TCP/UDP/进/线:{{ scope.row.tcp_count }}/{{ scope.row.udp_count }}/{{ scope.row.process_count }}/{{ scope.row.thread_count }}</p>
                  <h5>链接的IP</h5>
                  <p v-html="scope.row.connections" />
                </el-col>
                <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
                  <p>配置:{{ scope.row.isp }}</p>
                  <h5>关联网站列表:</h5>
                  <ul>
                    <li v-for="(item,index) in scope.row.websites" :key="index">{{ item.domain }}</li>
                  </ul>
                </el-col>
              </el-row>
            </div>
            <span slot="reference">{{ scope.row.isp }}</span>
          </el-popover>
        </template>
      </el-table-column>
      <el-table-column align="center" label="mysql" prop="mysql" sortable="custom">
        <template slot-scope="scope">
          <i v-if="scope.row.mysql" class="el-icon-circle-check" style="color: green" @click="handleLiveStatus(scope.row,'mysql')" />
          <i v-else class="el-icon-circle-close" style="color: red" />
          <el-dropdown
            split-button
            size="mini"
            style="float: right"
            @click="handleLiveStatus(scope.row,'mysql')"
          ><i class="el-icon-view" />
            <el-dropdown-menu slot="dropdown" size="mini">
              <el-dropdown-item size="mini" @click.native.stop="handleCommand(scope.row,'mysql_restart')">重启</el-dropdown-item>
              <el-dropdown-item class="clearfix">
                <a @click="handleViewMySqlDatabse(scope.row)">数据库管理</a>
              </el-dropdown-item>
            </el-dropdown-menu>
          </el-dropdown>
        </template>
      </el-table-column>
      <el-table-column align="center" label="apache" prop="apache" sortable="custom">
        <template slot-scope="scope">
          <i v-if="scope.row.apache" class="el-icon-circle-check" style="color: green" @click="handleLiveStatus(scope.row,'apache')" />
          <i v-else class="el-icon-circle-close" style="color: red" />
          <el-dropdown
            split-button
            size="mini"
            style="float: right"
            @click="handleLiveStatus(scope.row,'apache')"
          ><i class="el-icon-view" />
            <el-dropdown-menu slot="dropdown" size="mini">
              <el-dropdown-item size="mini" @click.native.stop="handleCommand(scope.row,'apache_restart')">重启</el-dropdown-item>
            </el-dropdown-menu>
          </el-dropdown>
        </template>
      </el-table-column>
      <el-table-column align="center" label="nginx" prop="nginx" sortable="custom">
        <template slot-scope="scope">
          <i v-if="scope.row.nginx" class="el-icon-circle-check" style="color: green" @click="handleLiveStatus(scope.row,'nginx')" />
          <i v-else class="el-icon-circle-close" style="color: red" @click="handleLiveStatus(scope.row,'nginx')" />

          <el-dropdown
            split-button
            size="mini"
            style="float: right"
            @click="handleLiveStatus(scope.row,'nginx')"
          ><i class="el-icon-view" />
            <el-dropdown-menu slot="dropdown" size="mini">
              <el-dropdown-item size="mini" @click.native.stop="handleCommand(scope.row,'nginx_restart')">重启</el-dropdown-item>
            </el-dropdown-menu>
          </el-dropdown>
        </template>
      </el-table-column>
      <el-table-column align="center" label="更新时间" prop="sync_at" sortable="custom" />
      <el-table-column align="center" label="操作" width="350" fixed="right">
        <template slot-scope="scope">
          <el-button
            v-show="scope.row.edit"
            type="success"
            size="mini"
            icon="el-icon-circle-check-outline"
            @click="confirmEdit(scope.row)"
          >
            确认
          </el-button>
          <el-button
            v-show="scope.row.edit"
            class="cancel-btn"
            size="mini"
            icon="el-icon-refresh"
            type="warning"
            @click="cancelEdit(scope.row)"
          >取消
          </el-button>
          <el-button
            v-show="!scope.row.edit"
            size="mini"
            icon="el-icon-info"
            type="info"
            plain
            @click="handleViewDetail(scope.row)"
          >查看
          </el-button>
          <el-button
            v-show="!scope.row.edit"
            size="mini"
            icon="el-icon-delete"
            type="danger"
            plain
            @click="handleAction('edit', scope.row)"
          >修改
          </el-button>

          <el-dropdown
            split-button
            type="success"
            size="mini"
            @click="sync(scope.row.id)"
          >同步
            <el-dropdown-menu slot="dropdown" size="mini">
              <el-dropdown-item @click.native.stop="handleLiveStatus(scope.row,'ps')">ps命令</el-dropdown-item>
              <el-dropdown-item @click.native.stop="handleLiveStatus(scope.row,'w')">w命令</el-dropdown-item>
              <el-dropdown-item @click.native.stop="showShell(scope.row)">其他命令</el-dropdown-item>
              <el-dropdown-item @click.native.stop="handleAction('delete', scope.row)">删除</el-dropdown-item>
            </el-dropdown-menu>
          </el-dropdown>
        </template>
      </el-table-column>

    </el-table>
    <el-button
      type="text"
      style="float: left"
      @click="vhostVisuable=true"
    >VHOST
    </el-button>
    <el-button
      type="text"
      style="float: left"
      @click="cloudflareVisuable=true"
    >CloudFlare
    </el-button>
    <el-button
      type="text"
      style="float: left"
      @click="merchantVisible=true"
    >Google Feed
    </el-button>
    <el-pagination
      v-if="data.length"
      background
      class="mt-pagination"
      :current-page="page"
      :page-sizes="[10,20,50,100]"
      :page-size="pagesize"
      layout="total, sizes, prev, pager, next, jumper"
      :total="total"
      @size-change="handleSizeChange"
      @current-change="handlePageChange"
    />
    <el-dialog
      :title="current_row.ip + '服务器状态详情'"
      :visible.sync="ServerDetailDialogVisible"
      width="50%"
      :close-on-click-modal="false"
      :close-on-press-escape="false"
    >
      <div>
        <el-row>
          <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
            <p>内存:{{ current_row.memory_used }}/{{ current_row.memory_total }}</p>
            <p>交换分区:{{ current_row.swap_used }}/{{ current_row.swap_total }}</p>
            <p>硬盘:{{ current_row.hdd_used }}/{{ current_row.hdd_total }}</p>
            <p>
              TCP/UDP/进/线:{{ current_row.tcp_count }}/{{ current_row.udp_count }}/{{ current_row.process_count }}/{{ current_row.thread_count }}</p>

          </el-col>
          <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
            <ul>
              <li v-for="(item,index) in current_row.websites" :key="index">{{ item.domain }}</li>
            </ul>
          </el-col>
        </el-row>
      </div>
      <span slot="footer" class="dialog-footer">
        <el-button type="primary" @click="ServerDetailDialogVisible = false">关 闭</el-button>
      </span>
    </el-dialog>

    <el-dialog
      :title="title"
      :visible.sync="dialogVisible"
      width="80%"
      :close-on-click-modal="false"
      :close-on-press-escape="false"
    >
      <el-form
        ref="dataForm"
        :model="temp"
        label-position="left"
        label-width="120px"
        style="margin-left: 8%"
      >

        <el-form-item label="绑定站点" label-width="80px">
          <el-transfer
            v-model="temp.websites"
            filterable
            :filter-method="filterMethod"
            :titles="['可选站点', '已选站点']"
            filter-placeholder="输入搜索"
            :data="websites"
            :props="{
              key: 'id',
              label: 'domain'
            }"
          />
        </el-form-item>

        <el-form-item v-if="action != 'bind'" label="gsapi ip:" label-width="120px">
          <el-input v-model="temp.gsapi_ip" />
        </el-form-item>

        <el-form-item v-if="action != 'bind'" label="gsapi port:" label-width="120px">
          <el-input v-model="temp.gsapi_port" />
        </el-form-item>
        <el-form-item v-if="action != 'bind'" label="ISP:" label-width="120px">
          <el-input v-model="temp.isp" />
        </el-form-item>
        <el-form-item v-if="action != 'bind'" label="更新频率:" label-width="120px">
          <el-input v-model="temp.sync_frequency">
            <template slot="append">分钟</template>
          </el-input>
        </el-form-item>
        <el-form-item v-if="action != 'bind'" label="db username:" label-width="120px">
          <el-input v-model="temp.db_username" />
        </el-form-item>
        <el-form-item v-if="action != 'bind'" label="db password:" label-width="120px">
          <el-input v-model="temp.db_password" />
        </el-form-item>
      </el-form>

      <span slot="footer" class="dialog-footer">
        <el-button :type="action !== 'delete'?'primary':'danger'" @click="confirm">确 定</el-button>
        <el-button @click="dialogVisible = false">取 消</el-button>
      </span>
    </el-dialog>

    <el-dialog
      :title="servertitle"
      :visible.sync="ServerDialogVisible"
      width="100%"
      :close-on-click-modal="false"
      :close-on-press-escape="false"
    >

      <div>
        <pre>{{ livestatus_response }}</pre>
      </div>
      <span slot="footer" class="dialog-footer">
        <el-button type="primary" @click="ServerDialogVisible = false">关 闭</el-button>
      </span>
    </el-dialog>

    <el-dialog
      :title="shelltitle"
      :visible.sync="shellDialogVisible"
      height="90%"
      width="80%"
      :close-on-click-modal="false"
      :close-on-press-escape="false"
    >
      <div>
        <el-container>
          <el-header>
            <div style="margin-top: 15px;">
              <el-autocomplete
                v-model="command"
                style="width: 90%"
                class="inline-input"
                :fetch-suggestions="querySearch"
                placeholder="请输入内容"
              />
              <el-button slot="append" type="success" icon="el-icon-position" :loading="shellloding" @click="handleCheckCmd">执行</el-button>
            </div>
          </el-header>
          <el-main>
            <pre>{{ shell_response }}</pre>
          </el-main>
        </el-container>

      </div>
      <span slot="footer" class="dialog-footer">
        <el-button type="primary" @click="shellDialogVisible = false">关 闭</el-button>
      </span>
    </el-dialog>
    <merchant :merchant-visible="merchantVisible" @closeMerchantDialog="merchantVisible=false" />
    <backups
      :is-visible="backupsVisuable"
      :website_domain="current_website_domain"
      :website_id="current_website_id"
      :ip="serverconfig_ip"
      :serverconfig_id="serverconfig_id"
      @closeMyDialog="backupsVisuable=false"
    />
    <mysqldatabase
      :is-visible="mysqldatabaseVisuable"
      :serverconfig_id="serverconfig_id"
      :websites="current_websites"
      @closeMyDialog="mysqldatabaseVisuable=false"
    />
    <cloudflareallinone :values-visible="cloudflareVisuable" @closeMyDialog="cloudflareVisuable=false" />
    <vhostrecord :m-visuable="vhostVisuable" @closeMyDialog="vhostVisuable=false" />
  </div>
</template>

<script>
import { Post, Put, Delete, Get, Sync, LiveStatus, CreateBackup } from '@/api/orders/serverstatus'
import merchant from '@/views/orders/element/merchant'
import {
  Get as GetWebsite
} from '@/api/erp/elicink/website'
import qs from 'qs'
import Backups from './element/backups'
import mysqldatabase from './element/mysqldatabase'
import cloudflareallinone from './element/cloudflareallinone'
import vhostrecord from './element/vhostrecord'

export default {
  name: 'Serverstatus',
  components: { vhostrecord, cloudflareallinone, mysqldatabase, Backups, merchant },
  data() {
    return {
      ServerDetailDialogVisible: false,
      current_row: {
        ip: '',
        websites: [],
        memory_used: 0,
        memory_total: 0,
        swap_total: 0,
        swap_used: 0,
        hdd_total: 0,
        hdd_used: 0,
        tcp_count: 0,
        udp_count: 0,
        process_count: 0,
        thread_count: 0
      },
      vhostVisuable: false,
      cloudflareVisuable: false,
      mysqldatabaseVisuable: false,
      current_websites: [],
      serverconfig_id: '',
      serverconfig_ip: '',
      current_website_id: '',
      current_website_domain: '',
      backupsVisuable: false,
      merchantVisible: false,
      command: '',
      shell_response: '',
      shellloding: false,
      shellDialogVisible: false,
      shellrow: '',
      shelltitle: '执行linux命令',
      servertitle: '服务器状态查询',
      ServerDialogVisible: false,
      livestatus_response: '',
      dialogVisible: false,
      data: [],
      action: '',
      title: '修改配置',
      websites: [],
      modify_id: '',
      temp: {
        gsapi_ip: '',
        gsapi_port: '',
        isp: 'Linode Cobly',
        sync_frequency: 60,
        db_username: 'mainshop',
        db_password: 'X8a14HfhhuZAfgNj',
        websites: []
      },
      websiteLoading: false,
      listLoading: true,
      // 输入
      kwInput: '',
      // pagination
      pagesize: 10,
      page: 1,
      total: 0,
      restaurants: []
    }
  },
  created() {
    this.fetchWebsites()
    this.getList()
  },
  mounted() {
    this.restaurants = this.loadAll()
  },
  methods: {
    querySearch(queryString, cb) {
      var restaurants = this.restaurants
      var results = queryString ? restaurants.filter(this.createFilter(queryString)) : restaurants
      // 调用 callback 返回建议列表的数据
      cb(results)
    },
    bytesToSize(bytes, precision) {
      let ret
      var kilobyte = 1024
      var megabyte = kilobyte * 1024
      var gigabyte = megabyte * 1024
      var terabyte = gigabyte * 1024

      if ((bytes >= 0) && (bytes < kilobyte)) {
        return bytes + ' B'
      } else if ((bytes >= kilobyte) && (bytes < megabyte)) {
        ret = (bytes / kilobyte).toFixed(precision) + ' K'
      } else if ((bytes >= megabyte) && (bytes < gigabyte)) {
        ret = (bytes / megabyte).toFixed(precision) + ' M'
      } else if ((bytes >= gigabyte) && (bytes < terabyte)) {
        ret = (bytes / gigabyte).toFixed(precision) + ' G'
      } else if (bytes >= terabyte) {
        ret = (bytes / terabyte).toFixed(precision) + ' T'
      } else {
        return bytes + ' B'
      }
      return ret + 'B'
    },
    handleViewDetail(row) {
      this.current_row.ip = row.gsapi_ip
      this.current_row.websites = row.websites
      this.current_row.memory_used = this.bytesToSize(row.memory_used * 1024, 2)
      this.current_row.memory_total = this.bytesToSize(row.memory_total * 1024, 2)
      this.current_row.hdd_total = this.bytesToSize(row.hdd_total * 1024 * 1024, 2)
      this.current_row.hdd_used = this.bytesToSize(row.hdd_used * 1024 * 1024, 2)
      this.current_row.swap_total = this.bytesToSize(row.swap_total * 1024, 2)
      this.current_row.swap_used = this.bytesToSize(row.swap_used * 1024, 2)
      this.current_row.tcp_count = row.tcp_count
      this.current_row.udp_count = row.udp_count
      this.current_row.process_count = row.process_count
      this.current_row.thread_count = row.thread_count

      this.ServerDetailDialogVisible = true
    },
    getList() {
      this.listLoading = true
      Get(null, qs.stringify({
        kw: this.kwInput,
        pagesize: this.pagesize,
        page: this.page
      }))
        .then(response => {
          this.data = response.data.data
          this.listLoading = false
          this.total = response.data.total
        }).catch(err => {
          console.log(err)
          this.listLoading = false
        })
    },
    resetTemp() {
      this.temp = {
        gsapi_ip: '',
        isp: 'Linode Cobly',
        gsapi_port: 8000,
        sync_frequency: 60,
        db_username: '',
        db_password: 'X8a14HfhhuZAfgNj',
        websites: []
      }
    },
    handleLiveStatus(row, command) {
      this.servertitle = row.website__domain + ' ' + command + '状态'
      this.listLoading = true
      LiveStatus(row.id, {
        command: command,
        type: 'common'
      }).then(response => {
        this.listLoading = false
        this.livestatus_response = response.data
        this.ServerDialogVisible = true
      })
    },
    handleViewBackups(row, website_id, website_domain) {
      this.serverconfig_id = row.id
      this.serverconfig_ip = row.gsapi_ip
      this.current_website_id = website_id
      this.current_website_domain = website_domain
      this.backupsVisuable = true
    },
    handleViewMySqlDatabse(row) {
      this.serverconfig_id = row.id
      this.current_websites = row.websites
      this.mysqldatabaseVisuable = true
    },
    handleCreateBackup(row) {
      this.listLoading = true
      CreateBackup(row.id, {}).then(response => {
        this.listLoading = false
        this.livestatus_response = response.data
        this.ServerDialogVisible = true
      })
    },
    showShell(row) {
      this.shellrow = row
      this.shellDialogVisible = true
    },
    handleCheckCmd() {
      this.shellloding = true
      this.shelltitle = this.shellrow.gsapi_ip + ' ' + this.command + 'linux命令'
      LiveStatus(this.shellrow.id, {
        command: this.command,
        type: 'checkcmd'
      }).then(response => {
        this.shellloding = false
        this.shell_response = response.data
      }).catch(err => {
        console.log(err)
        this.shellloding = false
      })
    },
    handleCommand(row, command) {
      this.$confirm('确定执行重要命令:' + command, '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        this.listLoading = true
        LiveStatus(row.id, {
          command: command,
          type: 'common'
        }).then(response => {
          this.listLoading = false
          this.livestatus_response = response.data
          this.ServerDialogVisible = true
        }).catch(err => {
          console.log(err)
          this.listLoading = false
        })
      }).catch(() => {
        this.$message({
          type: 'info',
          message: '取消执行'
        })
      })
    },
    handleAction(action, row) {
      this.action = action
      switch (action) {
        case 'create':
          this.dialogVisible = true
          this.title = row
          this.resetTemp()
          break
        case 'edit':
          this.modify_id = row.id
          this.temp.website_id = row.website_id
          this.temp.gsapi_ip = row.gsapi_ip
          this.temp.isp = row.isp
          this.temp.gsapi_port = row.gsapi_port
          this.temp.sync_frequency = row.sync_frequency
          this.temp.db_password = row.db_password
          this.temp.db_username = row.db_username
          this.temp.websites = row.websites.length > 0 ? row.websites.map(m => m.id) : []
          this.dialogVisible = true
          break
        case 'delete':
          this.dialogVisible = true
          this.title = `确认要删除${row.domain}?`
          this.temp = row
          break
        case 'bind':
          this.modify_id = row.id
          this.temp.websites = row.websites.length > 0 ? row.websites.map(m => m.id) : []
          this.dialogVisible = true
          break
      }
    },
    confirm() {
      const _data = this.temp
      switch (this.action) {
        case 'create':
          Post(_data).then(response => {
            this.dialogVisible = false
            this.getList()
            this.notify('添加成功')
          })
          return
        case 'edit':
          Put(this.modify_id, {
            websites: _data.websites,
            gsapi_ip: _data.gsapi_ip,
            gsapi_port: _data.gsapi_port,
            isp: _data.isp,
            sync_frequency: _data.sync_frequency,
            db_username: _data.db_username,
            db_password: _data.db_password
          }).then(response => {
            this.dialogVisible = false
            this.getList()
            this.notify('更新成功')
          })
          return
        case 'delete':
          Delete(_data.id).then((response) => {
            this.dialogVisible = false
            this.getList()
            this.notify('删除成功')
          })
          return
      }
    },
    sync(id) {
      this.listLoading = true
      Sync(id).then(response => {
        this.listLoading = false
        this.getList()
        this.notify('同步中，请等待后台程序的执行.')
      }).catch(err => {
        console.log(err)
        this.listLoading = false
      })
    },
    notify(message, duration) {
      this.$notify({
        title: '成功',
        message: message,
        type: 'success',
        duration: duration || 2000
      })
    },
    filterMethod(query, item) {
      return item.domain.indexOf(query) > -1
    },
    // 获取站点
    fetchWebsites() {
      GetWebsite().then(response => {
        this.websites = response.data.data
        this.websiteLoading = false
      }).catch(e => {
        this.websiteLoading = false
      })
    },
    // pageSize 改变后触发 table 更新
    handleSizeChange(val) {
      this.pagesize = val
      this.getList()
    },
    // page 改变后触发 table 更新
    handlePageChange(val) {
      this.page = val
      this.getList()
    },
    // 点击搜索
    handleSearch() {
      this.page = 1
      this.getList()
    },
    loadAll() {
      return [
        { 'value': 'ls /data/wwwlogs/' },
        { 'value': 'cd /home/gsapi;git pull;' },
        { 'value': 'cat -n 100 /var/log/gsapi-server.log' }
      ]
    }
  }
}
</script>

<style scoped>
  .el-tag + .el-tag {
    margin-left: 10px;
  }

  .top >>> .el-input {
    width: 80%;
  }

  .top >>> .input-with-select .el-input-group__prepend {
    background-color: #fff;
  }

  .app-container >>> .el-transfer-panel {
    width: 350px !important;
  }

  .top {
    padding-left: 20px;
    margin-bottom: 5px;
    margin-top: 28px;
  }

  .add-btn {
    float: right;
    margin-right: 20px;
    width: 150px
  }

  .mt-pagination {
    float: right;
    margin-top: 5px;
  }

  .app-container >>> .el-dialog {
    margin-top: 48px !important;
    margin-bottom: 5px;
  }

  .mt-form >>> .el-select {
    width: 100%;
  }

  .mt-form >>> .el-input__inner {
    width: 100%;
  }

  .mt-dialog >>> .el-dialog {
    margin: 10px auto !important;
  }

  .mt-dialog >>> .el-dialog__body {
    padding-bottom: 60px;
    padding-top: 5px;
  }

</style>
